<!DOCTYPE html>
<html>
<head>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
</head>
<body>
<script>
// This is not an external/wpt/webrtc/ test because it tests APIs and behaviors
// that are not in the spec.

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  pc.addStream(stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_equals(pc.getSenders().length, 1);
  assert_equals(pc.getSenders()[0].track, stream.getTracks()[0]);
}, 'addStream() adds to local streams and senders.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  let sender = pc.addTrack(stream.getTracks()[0], stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_array_equals(pc.getSenders(), [ sender ]);
}, 'addTrack() adds to local streams and senders.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  pc.addStream(stream);
  try {
    pc.addTrack(stream.getTracks()[0])
    assert_unreached('addTrack() should have failed.');
  } catch (e) {
    assert_equals(e.name, 'InvalidAccessError');
    assert_array_equals(pc.getLocalStreams(), [ stream ]);
  };
}, 'addTrack() fails after addStream().');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  let sender = pc.addTrack(stream.getTracks()[0]);
  assert_array_equals(pc.getLocalStreams(), []);
  assert_array_equals(pc.getSenders(), [ sender ]);
  pc.addStream(stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  let otherSender = pc.getSenders().find(s => {
    return s.track == stream.getTracks()[1];
  });
  assert_true(otherSender != null);
  assert_equals(pc.getSenders().length, 2);
}, 'addStream() after addTrack() adds the remaining track.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  let videoTrack = stream.getVideoTracks()[0];
  stream.removeTrack(videoTrack);

  pc.addStream(stream);
  assert_true(
      pc.getSenders().find(s => { return s.track == videoTrack; }) == null,
      'PC does not know about the videoTrack before stream.addTrack()');
  stream.addTrack(videoTrack);
  assert_true(
      pc.getSenders().find(s => { return s.track == videoTrack; }) != null,
      'PC knows about the videoTrack after stream.addTrack()');
}, 'Adding a track to an addStream()-stream adds it to the PC.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  let videoTrack = stream.getVideoTracks()[0];
  pc.addStream(stream);
  assert_true(
      pc.getSenders().find(s => { return s.track == videoTrack; }) != null,
      'PC knows about the track before stream.removeTrack()');
  stream.removeTrack(videoTrack);
  assert_true(
      pc.getSenders().find(s => { return s.track == videoTrack; }) == null,
      'PC does not know about the track after stream.removeTrack()');
}, 'Removing a track from an addStream()-stream removes it from the PC.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  let videoTrack = stream.getVideoTracks()[0];
  stream.removeTrack(videoTrack);

  pc.addStream(stream);
  pc.close();
  stream.addTrack(videoTrack);
}, 'Adding a track to an addStream()-stream after the PC closed is safe.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  let videoTrack = stream.getVideoTracks()[0];

  pc.addStream(stream);
  pc.close();
  stream.removeTrack(videoTrack);
}, 'Removing a track from an addStream()-stream after the PC closed is safe.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  let videoTrack = stream.getVideoTracks()[0];
  stream.removeTrack(videoTrack);

  pc.addStream(stream);
  pc.removeStream(stream);
  assert_true(
      pc.getSenders().find(s => { return s.track == videoTrack; }) == null,
      'PC does not know about the videoTrack before stream.addTrack()');
  stream.addTrack(videoTrack);
  assert_true(
      pc.getSenders().find(s => { return s.track == videoTrack; }) == null,
      'PC does not know about the videoTrack after stream.addTrack()');
}, 'The PC stops observing the stream after removeStream().');

promise_test(async t => {
  const pc = new RTCPeerConnection({sdpSemantics:'plan-b'});
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  pc.addStream(stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_equals(pc.getSenders().length, 1);
  pc.removeStream(stream);
  assert_array_equals(pc.getLocalStreams(), []);
  assert_array_equals(pc.getSenders(), []);
}, 'removeStream() after addStream() removes from local streams and senders.');

promise_test(async t => {
  const pc = new RTCPeerConnection({sdpSemantics:'plan-b'});
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  pc.addTrack(stream.getTracks()[0], stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_equals(pc.getSenders().length, 1);
  pc.removeStream(stream);
  assert_array_equals(pc.getLocalStreams(), []);
  assert_array_equals(pc.getSenders(), []);
}, 'removeStream() after addTrack() removes from local streams and senders.');

promise_test(async t => {
  const pc = new RTCPeerConnection({sdpSemantics:'plan-b'});
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true,
                                                          video:true});
  pc.addStream(stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  let senders = pc.getSenders();
  assert_equals(senders.length, 2);
  pc.removeTrack(senders[0]);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_array_equals(pc.getSenders(), [ senders[1] ]);
  pc.removeStream(stream);
  assert_array_equals(pc.getLocalStreams(), []);
  assert_array_equals(pc.getSenders(), []);
}, 'removeStream() after removeTrack() removes remaining tracks.');

promise_test(async t => {
  const pc = new RTCPeerConnection({sdpSemantics:'plan-b'});
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  pc.addStream(stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_equals(pc.getSenders().length, 1);
  pc.removeTrack(pc.getSenders()[0]);
  assert_array_equals(pc.getLocalStreams(), []);
  assert_array_equals(pc.getSenders(), []);
}, 'removeTrack() after addStream() removes from local streams and senders.');

promise_test(async t => {
  const pc = new RTCPeerConnection({sdpSemantics:'plan-b'});
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  let sender = pc.addTrack(stream.getTracks()[0], stream);
  assert_array_equals(pc.getLocalStreams(), [ stream ]);
  assert_array_equals(pc.getSenders(), [ sender ]);
  pc.removeTrack(sender);
  assert_array_equals(pc.getLocalStreams(), []);
  assert_array_equals(pc.getSenders(), []);
}, 'removeTrack() after addTrack() removes from local streams and senders.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  pc.addStream(stream);
  pc.createDTMFSender(stream.getTracks()[0]);
}, 'createDTMFSender() with addStream()-track.');

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());
  let stream = await navigator.mediaDevices.getUserMedia({audio:true});
  let track = stream.getTracks()[0];
  pc.addTrack(track);
  pc.createDTMFSender(track);
}, 'createDTMFSender() with addTrack()-track.');

</script>
</body>
</html>
